/* pshm_write.c

   Usage: pshm_write shm-name string

   Copy 'string' into the POSIX shared memory object named in 'shm-name'.

   See also pshm_read.c.
*/
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static void errExit(char *msg) {
  perror(msg);
  exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
  int fd;
  size_t len; /* Size of shared memory object */
  char *addr;

  if (argc != 3 || strcmp(argv[1], "--help") == 0) {
    fprintf(stderr, "%s shm-name string\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  fd = shm_open(argv[1], O_RDWR, 0); /* Open existing object */
  if (fd == -1) errExit("shm_open");

  len = strlen(argv[2]);
  if (ftruncate(fd, len) == -1) /* Resize object to hold string */
    errExit("ftruncate");
  printf("Resized to %ld bytes\n", (long)len);
  /*FIXME: above: should use %zu here, and remove (long) cast */

  addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (addr == MAP_FAILED) errExit("mmap");

  if (close(fd) == -1) /* 'fd' is no longer needed */
    errExit("close");

  printf("copying %ld bytes\n", (long)len);
  /*FIXME: above: should use %zu here, and remove (long) cast */
  memcpy(addr, argv[2], len); /* Copy string to shared memory */
  exit(EXIT_SUCCESS);
}